Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
fusion.h File Reference
+ Include dependency graph for fusion.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define FLPFSECS_1DOF_P_BASIC   1.5F
 
#define FLPFSECS_3DOF_G_BASIC   1.0F
 
#define FLPFSECS_3DOF_B_BASIC   7.0F
 
#define FMAX_6DOF_GY_BPL   7.0F
 
#define FMAX_9DOF_GBY_BPL   7.0F
 
COMPUTE_6DOF_GB_BASIC constants
#define FLPFSECS_6DOF_GB_BASIC   7.0F
 
COMPUTE_6DOF_GY_KALMAN constants
#define FQVY_6DOF_GY_KALMAN   2E2
 
#define FQVG_6DOF_GY_KALMAN   1.2E-3
 
#define FQWB_6DOF_GY_KALMAN   2E-2F
 
#define FMIN_6DOF_GY_BPL   -7.0F
 
COMPUTE_9DOF_GBY_KALMAN constants

gyro sensor noise covariance units deg^2 increasing this parameter improves convergence to the geomagnetic field

#define FQVY_9DOF_GBY_KALMAN   2E2
 
#define FQVG_9DOF_GBY_KALMAN   1.2E-3
 
#define FQVB_9DOF_GBY_KALMAN   5E0
 
#define FQWB_9DOF_GBY_KALMAN   2E-2F
 
#define FMIN_9DOF_GBY_BPL   -7.0F
 

Functions

Fusion Function Prototypes

These functions comprise the core of the basic sensor fusion functions excluding magnetic and acceleration calibration. Parameter descriptions are not included here, as details are provided in sensor_fusion.h.

void fInitializeFusion (SensorFusionGlobals *sfg)
 
void fFuseSensors (struct SV_1DOF_P_BASIC *pthisSV_1DOF_P_BASIC, struct SV_3DOF_G_BASIC *pthisSV_3DOF_G_BASIC, struct SV_3DOF_B_BASIC *pthisSV_3DOF_B_BASIC, struct SV_3DOF_Y_BASIC *pthisSV_3DOF_Y_BASIC, struct SV_6DOF_GB_BASIC *pthisSV_6DOF_GB_BASIC, struct SV_6DOF_GY_KALMAN *pthisSV_6DOF_GY_KALMAN, struct SV_9DOF_GBY_KALMAN *pthisSV_9DOF_GBY_KALMAN, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, struct GyroSensor *pthisGyro, struct PressureSensor *pthisPressure, struct MagCalibration *pthisMagCal)
 
void fInit_1DOF_P_BASIC (struct SV_1DOF_P_BASIC *pthisSV, struct PressureSensor *pthisPressure, float flpftimesecs)
 
void fInit_3DOF_G_BASIC (struct SV_3DOF_G_BASIC *pthisSV, struct AccelSensor *pthisAccel, float flpftimesecs)
 
void fInit_3DOF_B_BASIC (struct SV_3DOF_B_BASIC *pthisSV, struct MagSensor *pthisMag, float flpftimesecs)
 
void fInit_3DOF_Y_BASIC (struct SV_3DOF_Y_BASIC *pthisSV)
 
void fInit_6DOF_GB_BASIC (struct SV_6DOF_GB_BASIC *pthisSV, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, float flpftimesecs)
 
void fInit_6DOF_GY_KALMAN (struct SV_6DOF_GY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct GyroSensor *pthisGyro)
 
void fInit_9DOF_GBY_KALMAN (struct SV_9DOF_GBY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, struct GyroSensor *pthisGyro, struct MagCalibration *pthisMagCal)
 
void fRun_1DOF_P_BASIC (struct SV_1DOF_P_BASIC *pthisSV, struct PressureSensor *pthisPressure)
 
void fRun_3DOF_G_BASIC (struct SV_3DOF_G_BASIC *pthisSV, struct AccelSensor *pthisAccel)
 
void fRun_3DOF_B_BASIC (struct SV_3DOF_B_BASIC *pthisSV, struct MagSensor *pthisMag)
 
void fRun_3DOF_Y_BASIC (struct SV_3DOF_Y_BASIC *pthisSV, struct GyroSensor *pthisGyro)
 
void fRun_6DOF_GB_BASIC (struct SV_6DOF_GB_BASIC *pthisSV, struct MagSensor *pthisMag, struct AccelSensor *pthisAccel)
 
void fRun_6DOF_GY_KALMAN (struct SV_6DOF_GY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct GyroSensor *pthisGyro)
 
void fRun_9DOF_GBY_KALMAN (struct SV_9DOF_GBY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, struct GyroSensor *pthisGyro, struct MagCalibration *pthisMagCal)
 

Detailed Description

This file can be used to "tune" the performance of specific algorithms within the sensor fusion library. It also defines the lower level function definitions for specific algorithms. Normally, the higher level hooks in sensor_fusion.h will be used, and those shown here will be left alone.

Definition in file fusion.h.

Macro Definition Documentation

#define FLPFSECS_1DOF_P_BASIC   1.5F

Referenced by fRun_1DOF_P_BASIC().

#define FLPFSECS_3DOF_B_BASIC   7.0F

Referenced by fRun_3DOF_B_BASIC().

#define FLPFSECS_3DOF_G_BASIC   1.0F

Referenced by fRun_3DOF_G_BASIC().

#define FLPFSECS_6DOF_GB_BASIC   7.0F

Definition at line 57 of file fusion.h.

Referenced by fRun_6DOF_GB_BASIC().

#define FMAX_6DOF_GY_BPL   7.0F

Referenced by fInit_6DOF_GY_KALMAN().

#define FMAX_9DOF_GBY_BPL   7.0F
#define FMIN_6DOF_GY_BPL   -7.0F

minimum permissible power on gyro offsets (deg/s)

Definition at line 65 of file fusion.h.

Referenced by fInit_6DOF_GY_KALMAN().

#define FMIN_9DOF_GBY_BPL   -7.0F

minimum permissible power on gyro offsets (deg/s)

Definition at line 77 of file fusion.h.

Referenced by fInit_9DOF_GBY_KALMAN(), and fRun_6DOF_GY_KALMAN().

#define FQVB_9DOF_GBY_KALMAN   5E0

magnetometer sensor noise variance units uT^2 defining minimum deviation from geomagnetic sphere.

Definition at line 75 of file fusion.h.

Referenced by fRun_6DOF_GY_KALMAN().

#define FQVG_6DOF_GY_KALMAN   1.2E-3

accelerometer sensor noise variance units g^2

Definition at line 63 of file fusion.h.

Referenced by fRun_6DOF_GY_KALMAN().

#define FQVG_9DOF_GBY_KALMAN   1.2E-3

accelerometer sensor noise variance units g^2 defining minimum deviation from 1g sphere

Definition at line 74 of file fusion.h.

Referenced by fRun_6DOF_GY_KALMAN().

#define FQVY_6DOF_GY_KALMAN   2E2

gyro sensor noise variance units (deg/s)^2

Definition at line 62 of file fusion.h.

Referenced by fInit_6DOF_GY_KALMAN().

#define FQVY_9DOF_GBY_KALMAN   2E2

gyro sensor noise variance units (deg/s)^2

Definition at line 73 of file fusion.h.

Referenced by fInit_9DOF_GBY_KALMAN().

#define FQWB_6DOF_GY_KALMAN   2E-2F

gyro offset random walk units (deg/s)^2

Definition at line 64 of file fusion.h.

Referenced by fInit_6DOF_GY_KALMAN().

#define FQWB_9DOF_GBY_KALMAN   2E-2F

gyro offset random walk units (deg/s)^2

Definition at line 76 of file fusion.h.

Referenced by fInit_6DOF_GY_KALMAN(), and fInit_9DOF_GBY_KALMAN().

Function Documentation

void fFuseSensors ( struct SV_1DOF_P_BASIC pthisSV_1DOF_P_BASIC,
struct SV_3DOF_G_BASIC pthisSV_3DOF_G_BASIC,
struct SV_3DOF_B_BASIC pthisSV_3DOF_B_BASIC,
struct SV_3DOF_Y_BASIC pthisSV_3DOF_Y_BASIC,
struct SV_6DOF_GB_BASIC pthisSV_6DOF_GB_BASIC,
struct SV_6DOF_GY_KALMAN pthisSV_6DOF_GY_KALMAN,
struct SV_9DOF_GBY_KALMAN pthisSV_9DOF_GBY_KALMAN,
struct AccelSensor pthisAccel,
struct MagSensor pthisMag,
struct GyroSensor pthisGyro,
struct PressureSensor pthisPressure,
struct MagCalibration pthisMagCal 
)

Definition at line 86 of file fusion.c.

Referenced by runFusion().

98 {
99  // 1DOF Pressure: call the low pass filter algorithm
100 #if F_1DOF_P_BASIC
101  if (pthisSV_1DOF_P_BASIC)
102  {
103  ARM_systick_start_ticks(&(pthisSV_1DOF_P_BASIC->systick));
104  fRun_1DOF_P_BASIC(pthisSV_1DOF_P_BASIC, pthisPressure);
105  pthisSV_1DOF_P_BASIC->systick = ARM_systick_elapsed_ticks(pthisSV_1DOF_P_BASIC->systick);
106  }
107 #endif
108 
109  // 3DOF Accel Basic: call the tilt algorithm
110 #if F_3DOF_G_BASIC
111  if (pthisSV_3DOF_G_BASIC)
112  {
113  ARM_systick_start_ticks(&(pthisSV_3DOF_G_BASIC->systick));
114  fRun_3DOF_G_BASIC(pthisSV_3DOF_G_BASIC, pthisAccel);
115  pthisSV_3DOF_G_BASIC->systick = ARM_systick_elapsed_ticks(pthisSV_3DOF_G_BASIC->systick);
116  }
117 #endif
118 
119  // 3DOF Magnetometer Basic: call the 2D vehicle compass algorithm
120 #if F_3DOF_B_BASIC
121  if (pthisSV_3DOF_B_BASIC)
122  {
123  ARM_systick_start_ticks(&(pthisSV_3DOF_B_BASIC->systick));
124  fRun_3DOF_B_BASIC(pthisSV_3DOF_B_BASIC, pthisMag);
125  pthisSV_3DOF_B_BASIC->systick = ARM_systick_elapsed_ticks(pthisSV_3DOF_B_BASIC->systick);
126  }
127 #endif
128 
129  // 3DOF Gyro Basic: call the gyro integration algorithm
130 #if F_3DOF_Y_BASIC
131  if (pthisSV_3DOF_Y_BASIC)
132  {
133  ARM_systick_start_ticks(&(pthisSV_3DOF_Y_BASIC->systick));
134  fRun_3DOF_Y_BASIC(pthisSV_3DOF_Y_BASIC, pthisGyro);
135  pthisSV_3DOF_Y_BASIC->systick = ARM_systick_elapsed_ticks(pthisSV_3DOF_Y_BASIC->systick);
136  }
137 #endif
138 
139  // 6DOF Accel / Mag: Basic: call the eCompass orientation algorithm
140 #if F_6DOF_GB_BASIC
141  if (pthisSV_6DOF_GB_BASIC)
142  {
143  ARM_systick_start_ticks(&(pthisSV_6DOF_GB_BASIC->systick));
144  fRun_6DOF_GB_BASIC(pthisSV_6DOF_GB_BASIC, pthisMag, pthisAccel);
145  pthisSV_6DOF_GB_BASIC->systick = ARM_systick_elapsed_ticks(pthisSV_6DOF_GB_BASIC->systick);
146  }
147 #endif
148 
149  // 6DOF Accel / Gyro: call the Kalman filter orientation algorithm
150 #if F_6DOF_GY_KALMAN
151  if (pthisSV_6DOF_GY_KALMAN)
152  {
153  ARM_systick_start_ticks(&(pthisSV_6DOF_GY_KALMAN->systick));
154  fRun_6DOF_GY_KALMAN(pthisSV_6DOF_GY_KALMAN, pthisAccel, pthisGyro);
155  pthisSV_6DOF_GY_KALMAN->systick = ARM_systick_elapsed_ticks(pthisSV_6DOF_GY_KALMAN->systick);
156  }
157 #endif
158 
159  // 9DOF Accel / Mag / Gyro: call the Kalman filter orientation algorithm
160 #if F_9DOF_GBY_KALMAN
161  if (pthisSV_9DOF_GBY_KALMAN)
162  {
163  ARM_systick_start_ticks(&(pthisSV_9DOF_GBY_KALMAN->systick));
164  fRun_9DOF_GBY_KALMAN(pthisSV_9DOF_GBY_KALMAN, pthisAccel, pthisMag,
165  pthisGyro, pthisMagCal);
166  pthisSV_9DOF_GBY_KALMAN->systick = ARM_systick_elapsed_ticks(pthisSV_9DOF_GBY_KALMAN->systick);
167  }
168 #endif
169  return;
170 }
void fRun_1DOF_P_BASIC(struct SV_1DOF_P_BASIC *pthisSV, struct PressureSensor *pthisPressure)
Definition: fusion.c:447
void fRun_6DOF_GB_BASIC(struct SV_6DOF_GB_BASIC *pthisSV, struct MagSensor *pthisMag, struct AccelSensor *pthisAccel)
Definition: fusion.c:610
void fRun_9DOF_GBY_KALMAN(struct SV_9DOF_GBY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, struct GyroSensor *pthisGyro, struct MagCalibration *pthisMagCal)
int32_t systick
systick timer
int32_t systick
systick timer
void fRun_3DOF_B_BASIC(struct SV_3DOF_B_BASIC *pthisSV, struct MagSensor *pthisMag)
Definition: fusion.c:517
void fRun_3DOF_Y_BASIC(struct SV_3DOF_Y_BASIC *pthisSV, struct GyroSensor *pthisGyro)
Definition: fusion.c:562
int32 ARM_systick_elapsed_ticks(int32 start_ticks)
int32_t systick
systick timer
int32_t systick
systick timer;
void fRun_3DOF_G_BASIC(struct SV_3DOF_G_BASIC *pthisSV, struct AccelSensor *pthisAccel)
Definition: fusion.c:467
void fRun_6DOF_GY_KALMAN(struct SV_6DOF_GY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct GyroSensor *pthisGyro)
Definition: fusion.c:663
int32_t systick
systick timer
int32_t systick
systick timer
void ARM_systick_start_ticks(int32 *pstart)
int32_t systick
systick timer;

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInit_1DOF_P_BASIC ( struct SV_1DOF_P_BASIC pthisSV,
struct PressureSensor pthisPressure,
float  flpftimesecs 
)

Definition at line 172 of file fusion.c.

Referenced by fRun_1DOF_P_BASIC().

174 {
175  // set algorithm sampling interval (typically 25Hz) and low pass filter
176  // Note: the MPL3115 sensor only updates its output every 1s and is therefore repeatedly oversampled at 25Hz
177  // but executing the exponenial filter at the 25Hz rate also performs an interpolation giving smoother output.
178  // set algorithm sampling interval (typically 25Hz)
179  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
180 
181  // set low pass filter constant with maximum value 1.0 (all pass) decreasing to 0.0 (increasing low pass)
182  if (flpftimesecs > pthisSV->fdeltat)
183  pthisSV->flpf = pthisSV->fdeltat / flpftimesecs;
184  else
185  pthisSV->flpf = 1.0F;
186 
187  // initialize the low pass filters to current measurement
188  pthisSV->fLPH = pthisPressure->fH;
189  pthisSV->fLPT = pthisPressure->fT;
190 
191  // clear the reset flag
192  pthisSV->resetflag = false;
193 
194  return;
195 } // end fInit_1DOF_P_BASIC
float fLPH
low pass filtered height (m)
float fdeltat
fusion time interval (s)
float fLPT
low pass filtered temperature (C)
float flpf
low pass filter coefficient
float fH
most recent unaveraged height (m)
int8_t resetflag
flag to request re-initialization on next pass
float fT
most recent unaveraged temperature (C)
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads

+ Here is the caller graph for this function:

void fInit_3DOF_B_BASIC ( struct SV_3DOF_B_BASIC pthisSV,
struct MagSensor pthisMag,
float  flpftimesecs 
)

Definition at line 228 of file fusion.c.

Referenced by fRun_3DOF_B_BASIC().

230 {
231  // set algorithm sampling interval (typically 25Hz)
232  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
233 
234  // set low pass filter constant with maximum value 1.0 (all pass) decreasing to 0.0 (increasing low pass)
235  if (flpftimesecs > pthisSV->fdeltat)
236  pthisSV->flpf = pthisSV->fdeltat / flpftimesecs;
237  else
238  pthisSV->flpf = 1.0F;
239 
240  // initialize the low pass filtered magnetometer orientation matrix and quaternion using fBc
241 #if THISCOORDSYSTEM == NED
242  f3DOFMagnetometerMatrixNED(pthisSV->fLPR, pthisMag->fBc);
243 #elif THISCOORDSYSTEM == ANDROID
244  f3DOFMagnetometerMatrixAndroid(pthisSV->fLPR, pthisMag->fBc);
245 #else // WIN8
246  f3DOFMagnetometerMatrixWin8(pthisSV->fLPR, pthisMag->fBc);
247 #endif
248  fQuaternionFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPq));
249 
250  // update the default quaternion type supported to the most sophisticated
251  //if (globals.DefaultQuaternionPacketType < Q3M)
252  //globals.QuaternionPacketType = globals.DefaultQuaternionPacketType = Q3M;
253  // clear the reset flag
254  pthisSV->resetflag = false;
255 
256  return;
257 } // end fInit_3DOF_B_BASIC
void f3DOFMagnetometerMatrixNED(float fR[][3], float fBc[])
Aerospace NED magnetometer 3DOF flat eCompass function, computing rotation matrix fR...
Definition: orientation.c:215
float fdeltat
fusion time interval (s)
int8_t resetflag
flag to request re-initialization on next pass
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
void f3DOFMagnetometerMatrixWin8(float fR[][3], float fBc[])
Windows 8 magnetometer 3DOF flat eCompass function, computing rotation matrix fR. ...
Definition: orientation.c:275
float fBc[3]
averaged calibrated measurement (uT)
Quaternion fLPq
low pass filtered orientation quaternion
float fLPR[3][3]
low pass filtered orientation matrix
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
float flpf
low pass filter coefficient
void f3DOFMagnetometerMatrixAndroid(float fR[][3], float fBc[])
Android magnetometer 3DOF flat eCompass function, computing rotation matrix fR.
Definition: orientation.c:245

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInit_3DOF_G_BASIC ( struct SV_3DOF_G_BASIC pthisSV,
struct AccelSensor pthisAccel,
float  flpftimesecs 
)

Definition at line 197 of file fusion.c.

Referenced by fRun_3DOF_G_BASIC().

199 {
200  // set algorithm sampling interval (typically 25Hz)
201  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
202 
203  // set low pass filter constant with maximum value 1.0 (all pass) decreasing to 0.0 (increasing low pass)
204  if (flpftimesecs > pthisSV->fdeltat)
205  pthisSV->flpf = pthisSV->fdeltat / flpftimesecs;
206  else
207  pthisSV->flpf = 1.0F;
208 
209  // apply the tilt estimation algorithm to initialize the low pass orientation matrix and quaternion
210 #if THISCOORDSYSTEM == NED
211  f3DOFTiltNED(pthisSV->fLPR, pthisAccel->fGc);
212 #elif THISCOORDSYSTEM == ANDROID
213  f3DOFTiltAndroid(pthisSV->fLPR, pthisAccel->fGc);
214 #else // WIN8
215  f3DOFTiltWin8(pthisSV->fLPR, pthisAccel->fGc);
216 #endif
217  fQuaternionFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPq));
218 
219  // update the default quaternion type supported to the most sophisticated
220  //if (globals.DefaultQuaternionPacketType < Q3)
221  //globals.QuaternionPacketType = globals.DefaultQuaternionPacketType = Q3;
222  // clear the reset flag
223  pthisSV->resetflag = false;
224 
225  return;
226 } // end fInit_3DOF_G_BASIC
float flpf
low pass filter coefficient
void f3DOFTiltNED(float fR[][3], float fGc[])
Aerospace NED accelerometer 3DOF tilt function, computing rotation matrix fR.
float fdeltat
fusion time interval (s)
Quaternion fLPq
low pass filtered orientation quaternion
float fLPR[3][3]
low pass filtered orientation matrix
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
float fGc[3]
averaged precision calibrated measurement (g)
void f3DOFTiltAndroid(float fR[][3], float fGc[])
Android accelerometer 3DOF tilt function computing, rotation matrix fR.
int8_t resetflag
flag to request re-initialization on next pass
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
void f3DOFTiltWin8(float fR[][3], float fGc[])
Windows 8 accelerometer 3DOF tilt function computing, rotation matrix fR.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInit_3DOF_Y_BASIC ( struct SV_3DOF_Y_BASIC pthisSV)

Definition at line 259 of file fusion.c.

Referenced by fRun_3DOF_Y_BASIC().

260 {
261  // compute the sampling time intervals (secs)
262  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
263 
264  // initialize orientation estimate to flat
265  f3x3matrixAeqI(pthisSV->fR);
266  fqAeq1(&(pthisSV->fq));
267 
268  // update the default quaternion type supported to the most sophisticated
269  //if (globals.DefaultQuaternionPacketType < Q3G)
270  //globals.QuaternionPacketType = globals.DefaultQuaternionPacketType = Q3G;
271  // clear the reset flag
272  pthisSV->resetflag = false;
273 
274  return;
275 } // end fInit_3DOF_Y_BASIC
int8_t resetflag
flag to request re-initialization on next pass
void fqAeq1(Quaternion *pqA)
set a quaternion to the unit quaternion
Definition: orientation.c:1034
float fR[3][3]
unfiltered orientation matrix
Quaternion fq
unfiltered orientation quaternion
void f3x3matrixAeqI(float A[][3])
function sets the 3x3 matrix A to the identity matrix
Definition: matrix.c:45
float fdeltat
fusion filter sampling interval (s)
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInit_6DOF_GB_BASIC ( struct SV_6DOF_GB_BASIC pthisSV,
struct AccelSensor pthisAccel,
struct MagSensor pthisMag,
float  flpftimesecs 
)

Definition at line 277 of file fusion.c.

Referenced by fRun_6DOF_GB_BASIC().

280 {
281  float ftmp;
282 
283  // set algorithm sampling interval (typically 25Hz)
284  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
285 
286  // set low pass filter constant with maximum value 1.0 (all pass) decreasing to 0.0 (increasing low pass)
287  if (flpftimesecs > pthisSV->fdeltat)
288  pthisSV->flpf = pthisSV->fdeltat / flpftimesecs;
289  else
290  pthisSV->flpf = 1.0F;
291 
292  // initialize the instantaneous orientation matrix, inclination angle and quaternion
293 #if THISCOORDSYSTEM == NED
294  feCompassNED(pthisSV->fLPR, &(pthisSV->fLPDelta), &ftmp, &ftmp, pthisMag->fBc, pthisAccel->fGc, &ftmp, &ftmp );
295 #elif THISCOORDSYSTEM == ANDROID
296  feCompassAndroid(pthisSV->fLPR, &(pthisSV->fLPDelta), &ftmp, &ftmp, pthisMag->fBc, pthisAccel->fGc, &ftmp, &ftmp);
297 #else // WIN8
298  feCompassWin8(pthisSV->fLPR, &(pthisSV->fLPDelta), &ftmp, &ftmp, pthisMag->fBc, pthisAccel->fGc, &ftmp, &ftmp);
299 #endif
300  fQuaternionFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPq));
301 
302  // update the default quaternion type supported to the most sophisticated
303  //if (globals.DefaultQuaternionPacketType < Q6MA)
304  // globals.QuaternionPacketType = globals.DefaultQuaternionPacketType = Q6MA;
305 
306  // clear the reset flag
307  pthisSV->resetflag = false;
308 
309  return;
310 } // end fInit_6DOF_GB_BASIC
void feCompassAndroid(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Android: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle f...
Definition: orientation.c:359
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
float fBc[3]
averaged calibrated measurement (uT)
float fLPR[3][3]
low pass filtered orientation matrix
void feCompassWin8(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Win8: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDel...
Definition: orientation.c:433
int8_t resetflag
flag to request re-initialization on next pass
float fGc[3]
averaged precision calibrated measurement (g)
void feCompassNED(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
NED: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelt...
Definition: orientation.c:286
float fLPDelta
low pass filtered inclination angle (deg)
Quaternion fLPq
low pass filtered orientation quaternion
float fdeltat
fusion time interval (s)
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
float flpf
low pass filter coefficient

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInit_6DOF_GY_KALMAN ( struct SV_6DOF_GY_KALMAN pthisSV,
struct AccelSensor pthisAccel,
struct GyroSensor pthisGyro 
)

Definition at line 313 of file fusion.c.

Referenced by fRun_6DOF_GY_KALMAN().

316 {
317  float *pFlash; // pointer to flash float words
318  int8 i; // loop counter
319 
320  // compute and store useful product terms to save floating point calculations later
321  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
322  pthisSV->fQwbOver3 = FQWB_6DOF_GY_KALMAN / 3.0F;
323  pthisSV->fAlphaOver2 = FPIOVER180 * pthisSV->fdeltat / 2.0F;
324  pthisSV->fAlphaSqOver4 = pthisSV->fAlphaOver2 * pthisSV->fAlphaOver2;
325  pthisSV->fAlphaQwbOver6 = pthisSV->fAlphaOver2 * pthisSV->fQwbOver3;
327  pthisSV->fMaxGyroOffsetChange = sqrtf(fabs(FQWB_9DOF_GBY_KALMAN)) / (float) FUSION_HZ;
328 
329  // zero the a posteriori gyro offset and error vectors
330  for (i = CHX; i <= CHZ; i++)
331  {
332  pthisSV->fqgErrPl[i] = 0.0F;
333  pthisSV->fbErrPl[i] = 0.0F;
334  }
335 
336  // check to see if a gyro calibration exists in flash
337  // the standard value for erased flash is 0xFF in each byte but for portability check against 0x12345678
338  pFlash = (float *) (CALIBRATION_NVM_ADDR + GYRO_NVM_OFFSET);
339  if (*((uint32 *) pFlash++) == 0x12345678)
340  {
341  // copy the gyro calibration from flash into the state vector
342  for (i = CHX; i <= CHZ; i++) pthisSV->fbPl[i] = *(pFlash++);
343  }
344  else
345  {
346  // set the gyro offset to the current measurement if within limits
347  for (i = CHX; i <= CHZ; i++)
348  {
349  if ((pthisGyro->fYs[i] >= FMIN_6DOF_GY_BPL) &&
350  (pthisGyro->fYs[i] <= FMAX_6DOF_GY_BPL))
351  pthisSV->fbPl[i] = pthisGyro->fYs[i];
352  else
353  pthisSV->fbPl[i] = 0.0F;
354  }
355  }
356 
357  // initialize the a posteriori orientation state vector to the tilt orientation
358 #if THISCOORDSYSTEM == NED
359  f3DOFTiltNED(pthisSV->fRPl, pthisAccel->fGc);
360 #elif THISCOORDSYSTEM == ANDROID
361  f3DOFTiltAndroid(pthisSV->fRPl, pthisAccel->fGc);
362 #else // Win8
363  f3DOFTiltWin8(pthisSV->fRPl, pthisAccel->fGc);
364 #endif
365  fQuaternionFromRotationMatrix(pthisSV->fRPl, &(pthisSV->fqPl));
366 
367  // update the default quaternion type supported to the most sophisticated
368  //if (globals.DefaultQuaternionPacketType < Q6AG)
369  //globals.QuaternionPacketType = globals.DefaultQuaternionPacketType = Q6AG;
370 
371  // clear the reset flag
372  pthisSV->resetflag = false;
373 
374  return;
375 } // end fInit_6DOF_GY_KALMAN
float fbPl[3]
gyro offset (deg/s)
#define FMIN_6DOF_GY_BPL
minimum permissible power on gyro offsets (deg/s)
Definition: fusion.h:65
void f3DOFTiltNED(float fR[][3], float fGc[])
Aerospace NED accelerometer 3DOF tilt function, computing rotation matrix fR.
float fAlphaQwbOver6
(PI / 180 * fdeltat) * Qwb / 6
#define FQWB_9DOF_GBY_KALMAN
gyro offset random walk units (deg/s)^2
Definition: fusion.h:76
#define FPIOVER180
degrees to radians conversion = pi / 180
Definition: sensor_fusion.h:99
float fAlphaSqQvYQwbOver12
(PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12
#define FMAX_6DOF_GY_BPL
#define FQVY_6DOF_GY_KALMAN
gyro sensor noise variance units (deg/s)^2
Definition: fusion.h:62
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
float fMaxGyroOffsetChange
maximum permissible gyro offset change per iteration (deg/s)
uint32_t uint32
Definition: sensor_fusion.h:60
float fYs[3]
averaged measurement (deg/s)
float fbErrPl[3]
gyro offset error (deg/s)
float fGc[3]
averaged precision calibrated measurement (g)
float fAlphaSqOver4
(PI / 180 * fdeltat)^2 / 4
float fRPl[3][3]
a posteriori orientation matrix
#define CHZ
float fdeltat
sensor fusion interval (s)
void f3DOFTiltAndroid(float fR[][3], float fGc[])
Android accelerometer 3DOF tilt function computing, rotation matrix fR.
float fQwbOver3
Qwb / 3.
#define FQWB_6DOF_GY_KALMAN
gyro offset random walk units (deg/s)^2
Definition: fusion.h:64
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
Quaternion fqPl
a posteriori orientation quaternion
float fqgErrPl[3]
gravity vector tilt orientation quaternion error (dimensionless)
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
float fAlphaOver2
PI / 180 * fdeltat / 2.
int8_t resetflag
flag to request re-initialization on next pass
void f3DOFTiltWin8(float fR[][3], float fGc[])
Windows 8 accelerometer 3DOF tilt function computing, rotation matrix fR.
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInit_9DOF_GBY_KALMAN ( struct SV_9DOF_GBY_KALMAN pthisSV,
struct AccelSensor pthisAccel,
struct MagSensor pthisMag,
struct GyroSensor pthisGyro,
struct MagCalibration pthisMagCal 
)

Definition at line 378 of file fusion.c.

Referenced by fRun_6DOF_GY_KALMAN().

380 {
381  float ftmp;// scratch
382  float *pFlash;// pointer to flash float words
383  int8 i;// loop counter
384 
385  // compute and store useful product terms to save floating point calculations later
386  pthisSV->fdeltat = 1.0F / (float) FUSION_HZ;
387  pthisSV->fgdeltat = GTOMSEC2 * pthisSV->fdeltat;
388  pthisSV->fQwbOver3 = FQWB_9DOF_GBY_KALMAN / 3.0F;
389  pthisSV->fAlphaOver2 = FPIOVER180 * pthisSV->fdeltat / 2.0F;
390  pthisSV->fAlphaSqOver4 = pthisSV->fAlphaOver2 * pthisSV->fAlphaOver2;
391  pthisSV->fAlphaQwbOver6 = pthisSV->fAlphaOver2 * pthisSV->fQwbOver3;
393  pthisSV->fMaxGyroOffsetChange = sqrtf(fabs(FQWB_9DOF_GBY_KALMAN)) / (float)FUSION_HZ;
394 
395  // zero the a posteriori error vectors and inertial outputs
396  for (i = CHX; i <= CHZ; i++) {
397  pthisSV->fqgErrPl[i] = 0.0F;
398  pthisSV->fqmErrPl[i] = 0.0F;
399  pthisSV->fbErrPl[i] = 0.0F;
400  pthisSV->fVelGl[i] = 0.0F;
401  pthisSV->fDisGl[i] = 0.0F;
402  }
403 
404  // check to see if a gyro calibration exists in flash
405  // the standard value for erased flash is 0xFF in each byte but for portability check against 0x12345678
406  pFlash = (float *) (CALIBRATION_NVM_ADDR + GYRO_NVM_OFFSET);
407  if (*((uint32*) pFlash++) == 0x12345678) {
408  // copy the gyro calibration from flash into the state vector
409  for (i = CHX; i <= CHZ; i++)
410  pthisSV->fbPl[i] = *(pFlash++);
411  } else {
412  // set the gyro offset to the current measurement if within limits
413  for (i = CHX; i <= CHZ; i++) {
414  if ((pthisGyro->fYs[i] >= FMIN_9DOF_GBY_BPL) && (pthisGyro->fYs[i] <= FMAX_9DOF_GBY_BPL))
415  pthisSV->fbPl[i] = pthisGyro->fYs[i];
416  else
417  pthisSV->fbPl[i] = 0.0F;
418  }
419  }
420 
421  // initialize the posteriori orientation state vector to the instantaneous eCompass orientation
422  pthisSV->iFirstAccelMagLock = false;
423 #if THISCOORDSYSTEM == NED
424  feCompassNED(pthisSV->fRPl, &(pthisSV->fDeltaPl), &(pthisSV->fsinDeltaPl), &(pthisSV->fcosDeltaPl),
425  pthisMag->fBc, pthisAccel->fGc, &ftmp, &ftmp);
426 #elif THISCOORDSYSTEM == ANDROID
427  feCompassAndroid(pthisSV->fRPl, &(pthisSV->fDeltaPl), &(pthisSV->fsinDeltaPl), &(pthisSV->fcosDeltaPl),
428  pthisMag->fBc, pthisAccel->fGc, &ftmp, &ftmp);
429 #else // WIN8
430  feCompassWin8(pthisSV->fRPl, &(pthisSV->fDeltaPl), &(pthisSV->fsinDeltaPl), &(pthisSV->fcosDeltaPl),
431  pthisMag->fBc, pthisAccel->fGc, &ftmp, &ftmp);
432 #endif
433  fQuaternionFromRotationMatrix(pthisSV->fRPl, &(pthisSV->fqPl));
434 
435  // clear the reset flag
436  pthisSV->resetflag = false;
437 
438  return;
439 } // end fInit_9DOF_GBY_KALMAN
float fDeltaPl
a posteriori inclination angle from Kalman filter (deg)
#define FMIN_9DOF_GBY_BPL
minimum permissible power on gyro offsets (deg/s)
Definition: fusion.h:77
#define FQWB_9DOF_GBY_KALMAN
gyro offset random walk units (deg/s)^2
Definition: fusion.h:76
float fDisGl[3]
displacement (m) in global frame
#define FPIOVER180
degrees to radians conversion = pi / 180
Definition: sensor_fusion.h:99
Quaternion fqPl
a posteriori orientation quaternion
void feCompassAndroid(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Android: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle f...
Definition: orientation.c:359
float fVelGl[3]
velocity (m/s) in global frame
int8_t resetflag
flag to request re-initialization on next pass
float fAlphaSqOver4
(PI / 180 * fdeltat)^2 / 4
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
float fbPl[3]
gyro offset (deg/s)
#define GTOMSEC2
float fgdeltat
g (m/s2) * fdeltat
uint32_t uint32
Definition: sensor_fusion.h:60
float fBc[3]
averaged calibrated measurement (uT)
float fcosDeltaPl
cos(fDeltaPl)
void feCompassWin8(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Win8: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDel...
Definition: orientation.c:433
float fYs[3]
averaged measurement (deg/s)
float fAlphaQwbOver6
(PI / 180 * fdeltat) * Qwb / 6
float fGc[3]
averaged precision calibrated measurement (g)
float fMaxGyroOffsetChange
maximum permissible gyro offset change per iteration (deg/s)
float fsinDeltaPl
sin(fDeltaPl)
#define CHZ
#define FMAX_9DOF_GBY_BPL
float fdeltat
sensor fusion interval (s)
#define FQVY_9DOF_GBY_KALMAN
gyro sensor noise variance units (deg/s)^2
Definition: fusion.h:73
float fqgErrPl[3]
gravity vector tilt orientation quaternion error (dimensionless)
int8_t iFirstAccelMagLock
denotes that 9DOF orientation has locked to 6DOF eCompass
float fQwbOver3
Qwb / 3.
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
float fRPl[3][3]
a posteriori orientation matrix
void feCompassNED(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
NED: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelt...
Definition: orientation.c:286
float fAlphaOver2
PI / 180 * fdeltat / 2.
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
float fbErrPl[3]
gyro offset error (deg/s)
int8_t int8
Definition: sensor_fusion.h:55
float fqmErrPl[3]
geomagnetic vector tilt orientation quaternion error (dimensionless)
float fAlphaSqQvYQwbOver12
(PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fInitializeFusion ( SensorFusionGlobals sfg)

Definition at line 51 of file fusion.c.

Referenced by DecodeCommandBytes(), and initializeFusionEngine().

52 {
53  // reset the quaternion type to the default packet type
54  // sfg->pControlSubsystem->QuaternionPacketType = sfg->pControlSubsystem->DefaultQuaternionPacketType;
55 
56  // force a reset of all the algorithms next time they execute
57  // the initialization will result in the default and current quaternion being set to the most sophisticated
58  // algorithm supported by the build
59 #if F_1DOF_P_BASIC
60  sfg->SV_1DOF_P_BASIC.resetflag = true;
61 #endif
62 #if F_3DOF_B_BASIC
63  sfg->SV_3DOF_B_BASIC.resetflag = true;
64 #endif
65 #if F_3DOF_G_BASIC
66  sfg->SV_3DOF_G_BASIC.resetflag = true;
67 #endif
68 #if F_3DOF_Y_BASIC
69  sfg->SV_3DOF_Y_BASIC.resetflag = true;
70 #endif
71 #if F_6DOF_GB_BASIC
72  sfg->SV_6DOF_GB_BASIC.resetflag = true;
73 #endif
74 #if F_6DOF_GY_KALMAN
75  sfg->SV_6DOF_GY_KALMAN.resetflag = true;
76 #endif
77 #if F_9DOF_GBY_KALMAN
78  sfg->SV_9DOF_GBY_KALMAN.resetflag = true;
79 #endif
80 
81  // reset the loop counter to zero for first iteration
82  sfg->loopcounter = 0;
83  return;
84 }
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)

+ Here is the caller graph for this function:

void fRun_1DOF_P_BASIC ( struct SV_1DOF_P_BASIC pthisSV,
struct PressureSensor pthisPressure 
)

Definition at line 447 of file fusion.c.

Referenced by fFuseSensors().

449 {
450  // if requested, do a reset and return
451  if (pthisSV->resetflag)
452  {
453  fInit_1DOF_P_BASIC(pthisSV, pthisPressure, FLPFSECS_1DOF_P_BASIC);
454  return;
455  }
456 
457  // exponentially low pass filter the pressure and temperature.
458  // when executed at (typically) 25Hz, this filter interpolates the raw signals which are
459  // output every 1s in Auto Acquisition mode.
460  pthisSV->fLPH += pthisSV->flpf * (pthisPressure->fH - pthisSV->fLPH);
461  pthisSV->fLPT += pthisSV->flpf * (pthisPressure->fT - pthisSV->fLPT);
462 
463  return;
464 } // end fRun_1DOF_P_BASIC
float fLPH
low pass filtered height (m)
float fLPT
low pass filtered temperature (C)
void fInit_1DOF_P_BASIC(struct SV_1DOF_P_BASIC *pthisSV, struct PressureSensor *pthisPressure, float flpftimesecs)
Definition: fusion.c:172
float flpf
low pass filter coefficient
float fH
most recent unaveraged height (m)
int8_t resetflag
flag to request re-initialization on next pass
float fT
most recent unaveraged temperature (C)
#define FLPFSECS_1DOF_P_BASIC

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fRun_3DOF_B_BASIC ( struct SV_3DOF_B_BASIC pthisSV,
struct MagSensor pthisMag 
)

Definition at line 517 of file fusion.c.

Referenced by fFuseSensors().

518 {
519  // if requested, do a reset and return
520  if (pthisSV->resetflag)
521  {
522  fInit_3DOF_B_BASIC(pthisSV, pthisMag, FLPFSECS_3DOF_B_BASIC);
523  return;
524  }
525 
526  // calculate the 3DOF magnetometer orientation matrix from fBc
527 #if THISCOORDSYSTEM == NED
528  f3DOFMagnetometerMatrixNED(pthisSV->fR, pthisMag->fBc);
529 #elif THISCOORDSYSTEM == ANDROID
530  f3DOFMagnetometerMatrixAndroid(pthisSV->fR, pthisMag->fBc);
531 #else // WIN8
532  f3DOFMagnetometerMatrixWin8(pthisSV->fR, pthisMag->fBc);
533 #endif
534 
535  // compute the instantaneous quaternion and low pass filter
536  fQuaternionFromRotationMatrix(pthisSV->fR, &(pthisSV->fq));
537  fLPFOrientationQuaternion(&(pthisSV->fq), &(pthisSV->fLPq), pthisSV->flpf,
538  pthisSV->fdeltat, pthisSV->fOmega);
539 
540  // compute the low pass rotation matrix and rotation vector from low pass filtered quaternion
541  fRotationMatrixFromQuaternion(pthisSV->fLPR, &(pthisSV->fLPq));
542  fRotationVectorDegFromQuaternion(&(pthisSV->fLPq), pthisSV->fLPRVec);
543 
544  // calculate the Euler angles from the low pass orientation matrix
545 #if THISCOORDSYSTEM == NED
546  fNEDAnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
547  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
548  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
549 #elif THISCOORDSYSTEM == ANDROID
550  fAndroidAnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
551  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
552  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
553 #else // WIN8
554  fWin8AnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
555  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
556  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
557 #endif
558  return;
559 }
void f3DOFMagnetometerMatrixNED(float fR[][3], float fBc[])
Aerospace NED magnetometer 3DOF flat eCompass function, computing rotation matrix fR...
Definition: orientation.c:215
void fRotationMatrixFromQuaternion(float R[][3], const Quaternion *pq)
compute the rotation matrix from an orientation quaternion
Definition: orientation.c:822
float fR[3][3]
unfiltered orientation matrix
void fAndroidAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Android angles in degrees from the Android rotation matrix
Definition: orientation.c:564
void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the NED angles in degrees from the NED rotation matrix
Definition: orientation.c:508
float fdeltat
fusion time interval (s)
float fLPRho
low pass compass (deg)
int8_t resetflag
flag to request re-initialization on next pass
float fLPPsi
low pass yaw (deg)
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
void fLPFOrientationQuaternion(Quaternion *pq, Quaternion *pLPq, float flpf, float fdeltat, float fOmega[])
function low pass filters an orientation quaternion and computes virtual gyro rotation rate ...
Definition: orientation.c:912
void f3DOFMagnetometerMatrixWin8(float fR[][3], float fBc[])
Windows 8 magnetometer 3DOF flat eCompass function, computing rotation matrix fR. ...
Definition: orientation.c:275
float fLPThe
low pass pitch (deg)
float fBc[3]
averaged calibrated measurement (uT)
Quaternion fLPq
low pass filtered orientation quaternion
float fLPR[3][3]
low pass filtered orientation matrix
void fInit_3DOF_B_BASIC(struct SV_3DOF_B_BASIC *pthisSV, struct MagSensor *pthisMag, float flpftimesecs)
Definition: fusion.c:228
#define FLPFSECS_3DOF_B_BASIC
float fOmega[3]
angular velocity (deg/s)
float fLPRVec[3]
rotation vector
float fLPChi
low pass tilt from vertical (deg)
Quaternion fq
unfiltered orientation quaternion
void fRotationVectorDegFromQuaternion(Quaternion *pq, float rvecdeg[])
computes rotation vector (deg) from rotation quaternion
Definition: orientation.c:862
float flpf
low pass filter coefficient
float fLPPhi
low pass roll (deg)
void f3DOFMagnetometerMatrixAndroid(float fR[][3], float fBc[])
Android magnetometer 3DOF flat eCompass function, computing rotation matrix fR.
Definition: orientation.c:245
void fWin8AnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Windows 8 angles in degrees from the Windows 8 rotation matrix
Definition: orientation.c:621

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fRun_3DOF_G_BASIC ( struct SV_3DOF_G_BASIC pthisSV,
struct AccelSensor pthisAccel 
)

Definition at line 467 of file fusion.c.

Referenced by fFuseSensors().

469 {
470  // if requested, do a reset and return
471  if (pthisSV->resetflag)
472  {
473  fInit_3DOF_G_BASIC(pthisSV, pthisAccel, FLPFSECS_3DOF_G_BASIC);
474  return;
475  }
476 
477  // apply the tilt estimation algorithm to get the instantaneous orientation matrix
478 #if THISCOORDSYSTEM == NED
479  f3DOFTiltNED(pthisSV->fR, pthisAccel->fGc);
480 #elif THISCOORDSYSTEM == ANDROID
481  f3DOFTiltAndroid(pthisSV->fR, pthisAccel->fGc);
482 #else // WIN8
483  f3DOFTiltWin8(pthisSV->fR, pthisAccel->fGc);
484 #endif
485 
486  // compute the instantaneous quaternion and low pass filter
487  fQuaternionFromRotationMatrix(pthisSV->fR, &(pthisSV->fq));
488  fLPFOrientationQuaternion(&(pthisSV->fq), &(pthisSV->fLPq), pthisSV->flpf,
489  pthisSV->fdeltat, pthisSV->fOmega);
490 
491  // compute the low pass rotation matrix and rotation vector from low pass filtered quaternion
492  fRotationMatrixFromQuaternion(pthisSV->fLPR, &(pthisSV->fLPq));
493  fRotationVectorDegFromQuaternion(&(pthisSV->fLPq), pthisSV->fLPRVec);
494 
495  // calculate the Euler angles from the low pass orientation matrix
496 #if THISCOORDSYSTEM == NED
497  fNEDAnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
498  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
499  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
500 #elif THISCOORDSYSTEM == ANDROID
501  fAndroidAnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
502  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
503  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
504 #else // WIN8
505  fWin8AnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
506  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
507  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
508 #endif
509 
510  // force the yaw and compass angles to zero
511  pthisSV->fLPPsi = pthisSV->fLPRho = 0.0F;
512 
513  return;
514 } // end fRun_3DOF_G_BASIC
float flpf
low pass filter coefficient
float fLPRVec[3]
rotation vector
Quaternion fq
unfiltered orientation quaternion
void fRotationMatrixFromQuaternion(float R[][3], const Quaternion *pq)
compute the rotation matrix from an orientation quaternion
Definition: orientation.c:822
float fLPPhi
low pass roll (deg)
void f3DOFTiltNED(float fR[][3], float fGc[])
Aerospace NED accelerometer 3DOF tilt function, computing rotation matrix fR.
float fdeltat
fusion time interval (s)
#define FLPFSECS_3DOF_G_BASIC
void fAndroidAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Android angles in degrees from the Android rotation matrix
Definition: orientation.c:564
float fLPPsi
low pass yaw (deg)
Quaternion fLPq
low pass filtered orientation quaternion
void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the NED angles in degrees from the NED rotation matrix
Definition: orientation.c:508
float fLPR[3][3]
low pass filtered orientation matrix
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
void fLPFOrientationQuaternion(Quaternion *pq, Quaternion *pLPq, float flpf, float fdeltat, float fOmega[])
function low pass filters an orientation quaternion and computes virtual gyro rotation rate ...
Definition: orientation.c:912
float fLPChi
low pass tilt from vertical (deg)
float fR[3][3]
unfiltered orientation matrix
float fGc[3]
averaged precision calibrated measurement (g)
float fLPThe
low pass pitch (deg)
void f3DOFTiltAndroid(float fR[][3], float fGc[])
Android accelerometer 3DOF tilt function computing, rotation matrix fR.
int8_t resetflag
flag to request re-initialization on next pass
void fInit_3DOF_G_BASIC(struct SV_3DOF_G_BASIC *pthisSV, struct AccelSensor *pthisAccel, float flpftimesecs)
Definition: fusion.c:197
float fOmega[3]
angular velocity (deg/s)
float fLPRho
low pass compass (deg)
void fRotationVectorDegFromQuaternion(Quaternion *pq, float rvecdeg[])
computes rotation vector (deg) from rotation quaternion
Definition: orientation.c:862
void f3DOFTiltWin8(float fR[][3], float fGc[])
Windows 8 accelerometer 3DOF tilt function computing, rotation matrix fR.
void fWin8AnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Windows 8 angles in degrees from the Windows 8 rotation matrix
Definition: orientation.c:621

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fRun_3DOF_Y_BASIC ( struct SV_3DOF_Y_BASIC pthisSV,
struct GyroSensor pthisGyro 
)

Definition at line 562 of file fusion.c.

Referenced by fFuseSensors().

564 {
565  Quaternion ftmpq; // scratch quaternion
566  int8 i; // loop counter
567 
568  // if requested, do a reset and return
569  if (pthisSV->resetflag)
570  {
571  fInit_3DOF_Y_BASIC(pthisSV);
572  return;
573  }
574 
575  // perform an approximate gyro integration for this algorithm using the average of all gyro measurments
576  // in the FIFO rather than computing the products of the individual quaternions.
577  // the reason is this algorithm does not estimate and subtract the gyro offset so any loss of integration accuracy
578  // from using the average gyro measurement is irrelevant.
579  // calculate the angular velocity (deg/s) and rotation vector from the average measurement
580  for (i = CHX; i <= CHZ; i++) pthisSV->fOmega[i] = pthisGyro->fYs[i];
581 
582  // compute the incremental rotation quaternion ftmpq, rotate the orientation quaternion fq
583  // and re-normalize fq to prevent error propagation
584  fQuaternionFromRotationVectorDeg(&ftmpq, pthisSV->fOmega, pthisSV->fdeltat);
585  qAeqAxB(&(pthisSV->fq), &ftmpq);
586  fqAeqNormqA(&(pthisSV->fq));
587 
588  // get the rotation matrix and rotation vector from the orientation quaternion fq
589  fRotationMatrixFromQuaternion(pthisSV->fR, &(pthisSV->fq));
590  fRotationVectorDegFromQuaternion(&(pthisSV->fq), pthisSV->fRVec);
591 
592  // compute the Euler angles from the orientation matrix
593 #if THISCOORDSYSTEM == NED
594  fNEDAnglesDegFromRotationMatrix(pthisSV->fR, &(pthisSV->fPhi),
595  &(pthisSV->fThe), &(pthisSV->fPsi),
596  &(pthisSV->fRho), &(pthisSV->fChi));
597 #elif THISCOORDSYSTEM == ANDROID
598  fAndroidAnglesDegFromRotationMatrix(pthisSV->fR, &(pthisSV->fPhi),
599  &(pthisSV->fThe), &(pthisSV->fPsi),
600  &(pthisSV->fRho), &(pthisSV->fChi));
601 #else // WIN8
602  fWin8AnglesDegFromRotationMatrix(pthisSV->fR, &(pthisSV->fPhi),
603  &(pthisSV->fThe), &(pthisSV->fPsi),
604  &(pthisSV->fRho), &(pthisSV->fChi));
605 #endif
606  return;
607 } // end fRun_3DOF_Y_BASIC
void fRotationMatrixFromQuaternion(float R[][3], const Quaternion *pq)
compute the rotation matrix from an orientation quaternion
Definition: orientation.c:822
int8_t resetflag
flag to request re-initialization on next pass
void fAndroidAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Android angles in degrees from the Android rotation matrix
Definition: orientation.c:564
float fThe
pitch (deg)
float fChi
tilt from vertical (deg)
void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the NED angles in degrees from the NED rotation matrix
Definition: orientation.c:508
float fRVec[3]
rotation vector
void fQuaternionFromRotationVectorDeg(Quaternion *pq, const float rvecdeg[], float fscaling)
computes normalized rotation quaternion from a rotation vector (deg)
Definition: orientation.c:713
quaternion structure definition
Definition: orientation.h:37
float fYs[3]
averaged measurement (deg/s)
float fR[3][3]
unfiltered orientation matrix
Quaternion fq
unfiltered orientation quaternion
#define CHZ
void fInit_3DOF_Y_BASIC(struct SV_3DOF_Y_BASIC *pthisSV)
Definition: fusion.c:259
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
float fOmega[3]
angular velocity (deg/s)
float fdeltat
fusion filter sampling interval (s)
float fPsi
yaw (deg)
float fRho
compass (deg)
void fqAeqNormqA(Quaternion *pqA)
function normalizes a rotation quaternion and ensures q0 is non-negative
Definition: orientation.c:999
float fPhi
roll (deg)
void fRotationVectorDegFromQuaternion(Quaternion *pq, float rvecdeg[])
computes rotation vector (deg) from rotation quaternion
Definition: orientation.c:862
void qAeqAxB(Quaternion *pqA, const Quaternion *pqB)
function compute the quaternion product qA = qA * qB
Definition: orientation.c:969
int8_t int8
Definition: sensor_fusion.h:55
void fWin8AnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Windows 8 angles in degrees from the Windows 8 rotation matrix
Definition: orientation.c:621

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fRun_6DOF_GB_BASIC ( struct SV_6DOF_GB_BASIC pthisSV,
struct MagSensor pthisMag,
struct AccelSensor pthisAccel 
)

Definition at line 610 of file fusion.c.

Referenced by fFuseSensors().

612 {
613  float ftmp1, ftmp2, ftmp3, ftmp4;
614 
615  // if requested, do a reset and return
616  if (pthisSV->resetflag)
617  {
618  fInit_6DOF_GB_BASIC(pthisSV, pthisAccel, pthisMag,
620  return;
621  }
622 
623  // call the eCompass algorithm to get the instantaneous orientation matrix and inclination angle
624 #if THISCOORDSYSTEM == NED
625  feCompassNED(pthisSV->fR, &(pthisSV->fDelta), &ftmp1, &ftmp2, pthisMag->fBc, pthisAccel->fGc, &ftmp3, &ftmp4);
626 #elif THISCOORDSYSTEM == ANDROID
627  feCompassAndroid(pthisSV->fR, &(pthisSV->fDelta), &ftmp1, &ftmp2, pthisMag->fBc, pthisAccel->fGc, &ftmp3, &ftmp4);
628 #else // WIN8
629  feCompassWin8(pthisSV->fR, &(pthisSV->fDelta), &ftmp1, &ftmp2, pthisMag->fBc, pthisAccel->fGc, &ftmp3, &ftmp4);
630 #endif
631 
632  // compute the instantaneous quaternion and low pass filter
633  fQuaternionFromRotationMatrix(pthisSV->fR, &(pthisSV->fq));
634  fLPFOrientationQuaternion(&(pthisSV->fq), &(pthisSV->fLPq), pthisSV->flpf,
635  pthisSV->fdeltat, pthisSV->fOmega);
636 
637  // compute the low pass rotation matrix and rotation vector from low pass filtered quaternion
638  fRotationMatrixFromQuaternion(pthisSV->fLPR, &(pthisSV->fLPq));
639  fRotationVectorDegFromQuaternion(&(pthisSV->fLPq), pthisSV->fLPRVec);
640 
641  // calculate the Euler angles from the low pass orientation matrix
642 #if THISCOORDSYSTEM == NED
643  fNEDAnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
644  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
645  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
646 #elif THISCOORDSYSTEM == ANDROID
647  fAndroidAnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
648  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
649  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
650 #else // WIN8
651  fWin8AnglesDegFromRotationMatrix(pthisSV->fLPR, &(pthisSV->fLPPhi),
652  &(pthisSV->fLPThe), &(pthisSV->fLPPsi),
653  &(pthisSV->fLPRho), &(pthisSV->fLPChi));
654 #endif
655 
656  // low pass filter the geomagnetic inclination angle with a simple exponential filter
657  pthisSV->fLPDelta += pthisSV->flpf * (pthisSV->fDelta - pthisSV->fLPDelta);
658 
659  return;
660 } // end fRun_6DOF_GB_BASIC
#define FLPFSECS_6DOF_GB_BASIC
Definition: fusion.h:57
void fRotationMatrixFromQuaternion(float R[][3], const Quaternion *pq)
compute the rotation matrix from an orientation quaternion
Definition: orientation.c:822
float fOmega[3]
virtual gyro angular velocity (deg/s)
void fAndroidAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Android angles in degrees from the Android rotation matrix
Definition: orientation.c:564
Quaternion fq
unfiltered orientation quaternion
float fLPRVec[3]
rotation vector
void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the NED angles in degrees from the NED rotation matrix
Definition: orientation.c:508
void feCompassAndroid(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Android: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle f...
Definition: orientation.c:359
float fLPPhi
low pass roll (deg)
float fLPRho
low pass compass (deg)
void fQuaternionFromRotationMatrix(float R[][3], Quaternion *pq)
compute the orientation quaternion from a 3x3 rotation matrix
Definition: orientation.c:781
void fLPFOrientationQuaternion(Quaternion *pq, Quaternion *pLPq, float flpf, float fdeltat, float fOmega[])
function low pass filters an orientation quaternion and computes virtual gyro rotation rate ...
Definition: orientation.c:912
float fBc[3]
averaged calibrated measurement (uT)
float fLPR[3][3]
low pass filtered orientation matrix
void feCompassWin8(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
Win8: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDel...
Definition: orientation.c:433
float fDelta
unfiltered inclination angle (deg)
int8_t resetflag
flag to request re-initialization on next pass
float fLPPsi
low pass yaw (deg)
float fLPThe
low pass pitch (deg)
void fInit_6DOF_GB_BASIC(struct SV_6DOF_GB_BASIC *pthisSV, struct AccelSensor *pthisAccel, struct MagSensor *pthisMag, float flpftimesecs)
Definition: fusion.c:277
float fGc[3]
averaged precision calibrated measurement (g)
float fR[3][3]
unfiltered orientation matrix
float fLPChi
low pass tilt from vertical (deg)
void feCompassNED(float fR[][3], float *pfDelta, float *pfsinDelta, float *pfcosDelta, float fBc[], float fGc[], float *pfmodBc, float *pfmodGc)
NED: basic 6DOF e-Compass function, computing rotation matrix fR and magnetic inclination angle fDelt...
Definition: orientation.c:286
float fLPDelta
low pass filtered inclination angle (deg)
Quaternion fLPq
low pass filtered orientation quaternion
float fdeltat
fusion time interval (s)
void fRotationVectorDegFromQuaternion(Quaternion *pq, float rvecdeg[])
computes rotation vector (deg) from rotation quaternion
Definition: orientation.c:862
float flpf
low pass filter coefficient
void fWin8AnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Windows 8 angles in degrees from the Windows 8 rotation matrix
Definition: orientation.c:621

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fRun_6DOF_GY_KALMAN ( struct SV_6DOF_GY_KALMAN pthisSV,
struct AccelSensor pthisAccel,
struct GyroSensor pthisGyro 
)

Definition at line 663 of file fusion.c.

Referenced by fFuseSensors().

666 {
667  // local scalars and arrays
668  float ftmpMi3x1[3]; // temporary vector used for a priori calculations
669  float ftmp3DOF3x1[3]; // temporary vector used for 3DOF calculations
670  float ftmpA3x3[3][3]; // scratch 3x3 matrix
671  float fQvGQa; // accelerometer noise covariance to 1g sphere
672  float fC3x6ik; // element i, k of measurement matrix C
673  float fC3x6jk; // element j, k of measurement matrix C
674  float fmodGc; // modulus of fGc[]
675  Quaternion fqMi; // a priori orientation quaternion
676  Quaternion ftmpq; // scratch quaternion
677  float ftmp; // scratch float
678  int8 ierror; // matrix inversion error flag
679  int8 i,
680  j,
681  k; // loop counters
682 
683  // working arrays for 3x3 matrix inversion
684  float *pfRows[3];
685  int8 iColInd[3];
686  int8 iRowInd[3];
687  int8 iPivot[3];
688 
689  // if requested, do a reset initialization with no further processing
690  if (pthisSV->resetflag)
691  {
692  fInit_6DOF_GY_KALMAN(pthisSV, pthisAccel, pthisGyro);
693  return;
694  }
695 
696  // compute the average angular velocity (used for display only) from the average measurement minus gyro offset
697  for (i = CHX; i <= CHZ; i++)
698  pthisSV->fOmega[i] = (float) pthisGyro->iYs[i] *
699  pthisGyro->fDegPerSecPerCount -
700  pthisSV->fbPl[i];
701 
702  // initialize the a priori orientation quaternion fqMi to the previous iteration's a posteriori estimate
703  // and incrementally rotate fqMi by the contents of the gyro FIFO buffer
704  fqMi = pthisSV->fqPl;
705  if (pthisGyro->iFIFOCount > 0)
706  {
707  // set ftmp to the interval between the FIFO gyro measurements
708  ftmp = pthisSV->fdeltat / (float) pthisGyro->iFIFOCount;
709 
710  // normal case, loop over all the buffered gyroscope measurements
711  for (j = 0; j < pthisGyro->iFIFOCount; j++)
712  {
713  // calculate the instantaneous angular velocity subtracting the gyro offset
714  for (i = CHX; i <= CHZ; i++)
715  ftmpMi3x1[i] = (float) pthisGyro->iYsFIFO[j][i] *
716  pthisGyro->fDegPerSecPerCount -
717  pthisSV->fbPl[i];
718 
719  // compute the incremental rotation quaternion ftmpq and integrate the a priori orientation quaternion fqMi
720  fQuaternionFromRotationVectorDeg(&ftmpq, ftmpMi3x1, ftmp);
721  qAeqAxB(&fqMi, &ftmpq);
722  }
723  }
724  else
725  {
726  // special case with no new FIFO measurements, use the previous iteration's average gyro reading to compute
727  // the incremental rotation quaternion ftmpq and integrate the a priori orientation quaternion fqMi
728  fQuaternionFromRotationVectorDeg(&ftmpq, pthisSV->fOmega,
729  pthisSV->fdeltat);
730  qAeqAxB(&fqMi, &ftmpq);
731  }
732 
733  // set ftmp3DOF3x1 to the 3DOF gravity vector in the sensor frame
734  fmodGc = sqrtf(fabs(pthisAccel->fGc[CHX] * pthisAccel->fGc[CHX] +
735  pthisAccel->fGc[CHY] * pthisAccel->fGc[CHY] +
736  pthisAccel->fGc[CHZ] * pthisAccel->fGc[CHZ]));
737  if (fmodGc != 0.0F)
738  {
739  // normal non-freefall case
740  ftmp = 1.0F / fmodGc;
741  ftmp3DOF3x1[CHX] = pthisAccel->fGc[CHX] * ftmp;
742  ftmp3DOF3x1[CHY] = pthisAccel->fGc[CHY] * ftmp;
743  ftmp3DOF3x1[CHZ] = pthisAccel->fGc[CHZ] * ftmp;
744  }
745  else
746  {
747  // use zero tilt in case of freefall
748  ftmp3DOF3x1[CHX] = 0.0F;
749  ftmp3DOF3x1[CHY] = 0.0F;
750  ftmp3DOF3x1[CHZ] = 1.0F;
751  }
752 
753  // correct accelerometer gravity vector for different coordinate systems
754 #if THISCOORDSYSTEM == NED
755  // +1g in accelerometer z axis (z down) when PCB is flat so no correction needed
756 #elif THISCOORDSYSTEM == ANDROID
757  // +1g in accelerometer z axis (z up) when PCB is flat so negate the vector to obtain gravity
758  ftmp3DOF3x1[CHX] = -ftmp3DOF3x1[CHX];
759  ftmp3DOF3x1[CHY] = -ftmp3DOF3x1[CHY];
760  ftmp3DOF3x1[CHZ] = -ftmp3DOF3x1[CHZ];
761 #else // WIN8
762  // -1g in accelerometer z axis (z up) when PCB is flat so no correction needed
763 #endif
764 
765  // set ftmpMi3x1 to the a priori gravity vector in the sensor frame from the a priori quaternion
766  ftmpMi3x1[CHX] = 2.0F * (fqMi.q1 * fqMi.q3 - fqMi.q0 * fqMi.q2);
767  ftmpMi3x1[CHY] = 2.0F * (fqMi.q2 * fqMi.q3 + fqMi.q0 * fqMi.q1);
768  ftmpMi3x1[CHZ] = 2.0F * (fqMi.q0 * fqMi.q0 + fqMi.q3 * fqMi.q3) - 1.0F;
769 
770  // correct a priori gravity vector for different coordinate systems
771 #if THISCOORDSYSTEM == NED
772  // z axis is down (NED) so no correction needed
773 #else // ANDROID and WIN8
774  // z axis is up (ANDROID and WIN8 ENU) so no negate the vector to obtain gravity
775  ftmpMi3x1[CHX] = -ftmpMi3x1[CHX];
776  ftmpMi3x1[CHY] = -ftmpMi3x1[CHY];
777  ftmpMi3x1[CHZ] = -ftmpMi3x1[CHZ];
778 #endif
779 
780  // calculate the rotation quaternion between 3DOF and a priori gravity vectors (ignored minus signs cancel here)
781  // and copy the quaternion vector components to the measurement error vector fZErr
782  fveqconjgquq(&ftmpq, ftmp3DOF3x1, ftmpMi3x1);
783  pthisSV->fZErr[CHX] = ftmpq.q1;
784  pthisSV->fZErr[CHY] = ftmpq.q2;
785  pthisSV->fZErr[CHZ] = ftmpq.q3;
786 
787  // update Qw using the a posteriori error vectors from the previous iteration.
788  // as Qv increases or Qw decreases, K -> 0 and the Kalman filter is weighted towards the a priori prediction
789  // as Qv decreases or Qw increases, KC -> I and the Kalman filter is weighted towards the measurement.
790  // initialize Qw to all zeroes
791  for (i = 0; i < 6; i++)
792  for (j = 0; j < 6; j++) pthisSV->fQw6x6[i][j] = 0.0F;
793 
794  // partial diagonal gyro offset terms
795  pthisSV->fQw6x6[3][3] = pthisSV->fbErrPl[CHX] * pthisSV->fbErrPl[CHX];
796  pthisSV->fQw6x6[4][4] = pthisSV->fbErrPl[CHY] * pthisSV->fbErrPl[CHY];
797  pthisSV->fQw6x6[5][5] = pthisSV->fbErrPl[CHZ] * pthisSV->fbErrPl[CHZ];
798 
799  // diagonal gravity vector components
800  pthisSV->fQw6x6[0][0] = pthisSV->fqgErrPl[CHX] *
801  pthisSV->fqgErrPl[CHX] +
802  pthisSV->fAlphaSqQvYQwbOver12 +
803  pthisSV->fAlphaSqOver4 *
804  pthisSV->fQw6x6[3][3];
805  pthisSV->fQw6x6[1][1] = pthisSV->fqgErrPl[CHY] *
806  pthisSV->fqgErrPl[CHY] +
807  pthisSV->fAlphaSqQvYQwbOver12 +
808  pthisSV->fAlphaSqOver4 *
809  pthisSV->fQw6x6[4][4];
810  pthisSV->fQw6x6[2][2] = pthisSV->fqgErrPl[CHZ] *
811  pthisSV->fqgErrPl[CHZ] +
812  pthisSV->fAlphaSqQvYQwbOver12 +
813  pthisSV->fAlphaSqOver4 *
814  pthisSV->fQw6x6[5][5];
815 
816  // remaining diagonal gyro offset components
817  pthisSV->fQw6x6[3][3] += pthisSV->fQwbOver3;
818  pthisSV->fQw6x6[4][4] += pthisSV->fQwbOver3;
819  pthisSV->fQw6x6[5][5] += pthisSV->fQwbOver3;
820 
821  // off diagonal gravity and gyro offset components
822  pthisSV->fQw6x6[0][3] = pthisSV->fQw6x6[3][0] = pthisSV->fqgErrPl[CHX] *
823  pthisSV->fbErrPl[CHX] -
824  pthisSV->fAlphaOver2 *
825  pthisSV->fQw6x6[3][3];
826  pthisSV->fQw6x6[1][4] = pthisSV->fQw6x6[4][1] = pthisSV->fqgErrPl[CHY] *
827  pthisSV->fbErrPl[CHY] -
828  pthisSV->fAlphaOver2 *
829  pthisSV->fQw6x6[4][4];
830  pthisSV->fQw6x6[2][5] = pthisSV->fQw6x6[5][2] = pthisSV->fqgErrPl[CHZ] *
831  pthisSV->fbErrPl[CHZ] -
832  pthisSV->fAlphaOver2 *
833  pthisSV->fQw6x6[5][5];
834 
835  // calculate the vector fQv containing the diagonal elements of the measurement covariance matrix Qv
836  ftmp = fmodGc - 1.0F;
837  fQvGQa = 3.0F * ftmp * ftmp;
838  if (fQvGQa < FQVG_6DOF_GY_KALMAN) fQvGQa = FQVG_6DOF_GY_KALMAN;
839  pthisSV->fQv = ONEOVER12 * ftmp * ftmp + pthisSV->fAlphaSqQvYQwbOver12;
840 
841  // calculate the 6x3 Kalman gain matrix K = Qw * C^T * inv(C * Qw * C^T + Qv)
842  // set fQwCT6x3 = Qw.C^T where Qw has size 6x6 and C^T has size 6x3
843  for (i = 0; i < 6; i++) // loop over rows
844  {
845  for (j = 0; j < 3; j++) // loop over columns
846  {
847  pthisSV->fQwCT6x3[i][j] = 0.0F;
848 
849  // accumulate matrix sum
850  for (k = 0; k < 6; k++)
851  {
852  // determine fC3x6[j][k] since the matrix is highly sparse
853  fC3x6jk = 0.0F;
854  if (k == j) fC3x6jk = 1.0F;
855  if (k == (j + 3)) fC3x6jk = -pthisSV->fAlphaOver2;
856 
857  // accumulate fQwCT6x3[i][j] += Qw6x6[i][k] * C[j][k]
858  if ((pthisSV->fQw6x6[i][k] != 0.0F) && (fC3x6jk != 0.0F))
859  {
860  if (fC3x6jk == 1.0F)
861  pthisSV->fQwCT6x3[i][j] += pthisSV->fQw6x6[i][k];
862  else
863  pthisSV->fQwCT6x3[i][j] += pthisSV->fQw6x6[i][k] * fC3x6jk;
864  }
865  }
866  }
867  }
868 
869  // set symmetric ftmpA3x3 = C.(Qw.C^T) + Qv = C.fQwCT6x3 + Qv
870  for (i = 0; i < 3; i++) // loop over rows
871  {
872  for (j = i; j < 3; j++) // loop over on and above diagonal columns
873  {
874  // zero off diagonal and set diagonal to Qv
875  if (i == j)
876  ftmpA3x3[i][j] = pthisSV->fQv;
877  else
878  ftmpA3x3[i][j] = 0.0F;
879 
880  // accumulate matrix sum
881  for (k = 0; k < 6; k++)
882  {
883  // determine fC3x6[i][k]
884  fC3x6ik = 0.0F;
885  if (k == i) fC3x6ik = 1.0F;
886  if (k == (i + 3)) fC3x6ik = -pthisSV->fAlphaOver2;
887 
888  // accumulate ftmpA3x3[i][j] += C[i][k] & fQwCT6x3[k][j]
889  if ((fC3x6ik != 0.0F) && (pthisSV->fQwCT6x3[k][j] != 0.0F))
890  {
891  if (fC3x6ik == 1.0F)
892  ftmpA3x3[i][j] += pthisSV->fQwCT6x3[k][j];
893  else
894  ftmpA3x3[i][j] += fC3x6ik * pthisSV->fQwCT6x3[k][j];
895  }
896  }
897  }
898  }
899 
900  // set ftmpA3x3 below diagonal elements to above diagonal elements
901  ftmpA3x3[1][0] = ftmpA3x3[0][1];
902  ftmpA3x3[2][0] = ftmpA3x3[0][2];
903  ftmpA3x3[2][1] = ftmpA3x3[1][2];
904 
905  // invert ftmpA3x3 in situ to give ftmpA3x3 = inv(C * Qw * C^T + Qv) = inv(ftmpA3x3)
906  for (i = 0; i < 3; i++) pfRows[i] = ftmpA3x3[i];
907  fmatrixAeqInvA(pfRows, iColInd, iRowInd, iPivot, 3, &ierror);
908 
909  // on successful inversion set Kalman gain matrix fK6x3 = Qw * C^T * inv(C * Qw * C^T + Qv) = fQwCT6x3 * ftmpA3x3
910  if (!ierror)
911  {
912  // normal case
913  for (i = 0; i < 6; i++) // loop over rows
914  {
915  for (j = 0; j < 3; j++) // loop over columns
916  {
917  pthisSV->fK6x3[i][j] = 0.0F;
918  for (k = 0; k < 3; k++)
919  {
920  if ((pthisSV->fQwCT6x3[i][k] != 0.0F) &&
921  (ftmpA3x3[k][j] != 0.0F))
922  {
923  pthisSV->fK6x3[i][j] += pthisSV->fQwCT6x3[i][k] * ftmpA3x3[k][j];
924  }
925  }
926  }
927  }
928  }
929  else
930  {
931  // ftmpA3x3 was singular so set Kalman gain matrix fK6x3 to zero
932  for (i = 0; i < 6; i++) // loop over rows
933  {
934  for (j = 0; j < 3; j++) // loop over columns
935  {
936  pthisSV->fK6x3[i][j] = 0.0F;
937  }
938  }
939  }
940 
941  // calculate the a posteriori gravity and geomagnetic tilt quaternion errors and gyro offset error vector
942  // from the Kalman matrix fK6x3 and from the measurement error vector fZErr.
943  for (i = CHX; i <= CHZ; i++)
944  {
945  // gravity tilt vector error component
946  if (pthisSV->fK6x3[i][CHX] != 0.0F)
947  pthisSV->fqgErrPl[i] = pthisSV->fK6x3[i][CHX] * pthisSV->fZErr[CHX];
948  else
949  pthisSV->fqgErrPl[i] = 0.0F;
950  if (pthisSV->fK6x3[i][CHY] != 0.0F)
951  pthisSV->fqgErrPl[i] += pthisSV->fK6x3[i][CHY] * pthisSV->fZErr[CHY];
952  if (pthisSV->fK6x3[i][CHZ] != 0.0F)
953  pthisSV->fqgErrPl[i] += pthisSV->fK6x3[i][CHZ] * pthisSV->fZErr[CHZ];
954 
955  // gyro offset vector error component
956  if (pthisSV->fK6x3[i + 3][CHX] != 0.0F)
957  pthisSV->fbErrPl[i] = pthisSV->fK6x3[i + 3][CHX] * pthisSV->fZErr[CHX];
958  else
959  pthisSV->fbErrPl[i] = 0.0F;
960  if (pthisSV->fK6x3[i + 3][CHY] != 0.0F)
961  pthisSV->fbErrPl[i] += pthisSV->fK6x3[i + 3][CHY] * pthisSV->fZErr[CHY];
962  if (pthisSV->fK6x3[i + 3][CHZ] != 0.0F)
963  pthisSV->fbErrPl[i] += pthisSV->fK6x3[i + 3][CHZ] * pthisSV->fZErr[CHZ];
964  }
965 
966  // set ftmpq to the gravity tilt correction (conjugate) quaternion
967  ftmpq.q1 = -pthisSV->fqgErrPl[CHX];
968  ftmpq.q2 = -pthisSV->fqgErrPl[CHY];
969  ftmpq.q3 = -pthisSV->fqgErrPl[CHZ];
970  ftmp = ftmpq.q1 * ftmpq.q1 + ftmpq.q2 * ftmpq.q2 + ftmpq.q3 * ftmpq.q3;
971 
972  // determine the scalar component q0 to enforce normalization
973  if (ftmp <= 1.0F)
974  {
975  // normal case
976  ftmpq.q0 = sqrtf(fabsf(1.0F - ftmp));
977  }
978  else
979  {
980  // if vector component exceeds unity then set to 180 degree rotation and force normalization
981  ftmp = 1.0F / sqrtf(ftmp);
982  ftmpq.q0 = 0.0F;
983  ftmpq.q1 *= ftmp;
984  ftmpq.q2 *= ftmp;
985  ftmpq.q3 *= ftmp;
986  }
987 
988  // apply the gravity tilt correction quaternion so fqPl = fqMi.(fqgErrPl)* = fqMi.ftmpq and normalize
989  qAeqBxC(&(pthisSV->fqPl), &fqMi, &ftmpq);
990 
991  // normalize the a posteriori quaternion and compute the a posteriori rotation matrix and rotation vector
992  fqAeqNormqA(&(pthisSV->fqPl));
993  fRotationMatrixFromQuaternion(pthisSV->fRPl, &(pthisSV->fqPl));
994  fRotationVectorDegFromQuaternion(&(pthisSV->fqPl), pthisSV->fRVecPl);
995 
996  // update the a posteriori gyro offset vector: b+[k] = b-[k] - be+[k] = b+[k] - be+[k] (deg/s)
997  // limiting the correction to the maximum permitted by the random walk model
998  for (i = CHX; i <= CHZ; i++)
999  {
1000  if (pthisSV->fbErrPl[i] > pthisSV->fMaxGyroOffsetChange)
1001  pthisSV->fbPl[i] -= pthisSV->fMaxGyroOffsetChange;
1002  else if (pthisSV->fbErrPl[i] < -pthisSV->fMaxGyroOffsetChange)
1003  pthisSV->fbPl[i] += pthisSV->fMaxGyroOffsetChange;
1004  else
1005  pthisSV->fbPl[i] -= pthisSV->fbErrPl[i];
1006  }
1007 
1008  // compute the linear acceleration fAccGl in the global frame
1009  // first de-rotate the accelerometer measurement fGc from the sensor to global frame
1010  // using the transpose (inverse) of the orientation matrix fRPl
1011  fveqRu(pthisSV->fAccGl, pthisSV->fRPl, pthisAccel->fGc, 1);
1012 
1013  // sutract the fixed gravity vector in the global frame leaving linear acceleration
1014 #if THISCOORDSYSTEM == NED
1015  // gravity positive NED
1016  pthisSV->fAccGl[CHX] = -pthisSV->fAccGl[CHX];
1017  pthisSV->fAccGl[CHY] = -pthisSV->fAccGl[CHY];
1018  pthisSV->fAccGl[CHZ] = -(pthisSV->fAccGl[CHZ] - 1.0F);
1019 #elif THISCOORDSYSTEM == ANDROID
1020  // acceleration positive ENU
1021  pthisSV->fAccGl[CHZ] = pthisSV->fAccGl[CHZ] - 1.0F;
1022 #else // WIN8
1023  // gravity positive ENU
1024  pthisSV->fAccGl[CHX] = -pthisSV->fAccGl[CHX];
1025  pthisSV->fAccGl[CHY] = -pthisSV->fAccGl[CHY];
1026  pthisSV->fAccGl[CHZ] = -(pthisSV->fAccGl[CHZ] + 1.0F);
1027 #endif
1028 
1029  // compute the a posteriori Euler angles from the a posteriori orientation matrix fRPl
1030 #if THISCOORDSYSTEM == NED
1031  fNEDAnglesDegFromRotationMatrix(pthisSV->fRPl, &(pthisSV->fPhiPl),
1032  &(pthisSV->fThePl), &(pthisSV->fPsiPl),
1033  &(pthisSV->fRhoPl), &(pthisSV->fChiPl));
1034 #elif THISCOORDSYSTEM == ANDROID
1035  fAndroidAnglesDegFromRotationMatrix(pthisSV->fRPl, &(pthisSV->fPhiPl),
1036  &(pthisSV->fThePl), &(pthisSV->fPsiPl),
1037  &(pthisSV->fRhoPl), &(pthisSV->fChiPl));
1038 #else // WIN8
1039  fWin8AnglesDegFromRotationMatrix(pthisSV->fRPl, &(pthisSV->fPhiPl),
1040  &(pthisSV->fThePl), &(pthisSV->fPsiPl),
1041  &(pthisSV->fRhoPl), &(pthisSV->fChiPl));
1042 #endif
1043  return;
1044 } // end fRun_6DOF_GY_KALMAN
float fbPl[3]
gyro offset (deg/s)
float fChiPl
tilt from vertical (deg)
void fmatrixAeqInvA(float *A[], int8 iColInd[], int8 iRowInd[], int8 iPivot[], int8 isize, int8 *pierror)
function uses Gauss-Jordan elimination to compute the inverse of matrix A in situ on exit...
Definition: matrix.c:666
void fRotationMatrixFromQuaternion(float R[][3], const Quaternion *pq)
compute the rotation matrix from an orientation quaternion
Definition: orientation.c:822
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
void fAndroidAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Android angles in degrees from the Android rotation matrix
Definition: orientation.c:564
float fThePl
pitch (deg)
float q0
scalar component
Definition: orientation.h:39
float fAlphaSqQvYQwbOver12
(PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12
uint8_t iFIFOCount
number of measurements read from FIFO
void fNEDAnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the NED angles in degrees from the NED rotation matrix
Definition: orientation.c:508
float fZErr[3]
measurement error vector
float q3
z vector component
Definition: orientation.h:42
float fMaxGyroOffsetChange
maximum permissible gyro offset change per iteration (deg/s)
#define FQVG_6DOF_GY_KALMAN
accelerometer sensor noise variance units g^2
Definition: fusion.h:63
void fQuaternionFromRotationVectorDeg(Quaternion *pq, const float rvecdeg[], float fscaling)
computes normalized rotation quaternion from a rotation vector (deg)
Definition: orientation.c:713
quaternion structure definition
Definition: orientation.h:37
float fPsiPl
yaw (deg)
float fQw6x6[6][6]
covariance matrix Qw
void qAeqBxC(Quaternion *pqA, const Quaternion *pqB, const Quaternion *pqC)
function compute the quaternion product qB * qC
Definition: orientation.c:958
float fbErrPl[3]
gyro offset error (deg/s)
float fPhiPl
roll (deg)
void fveqconjgquq(Quaternion *pfq, float fu[], float fv[])
function computes the rotation quaternion that rotates unit vector u onto unit vector v as v=q*...
Definition: orientation.c:1044
float fRhoPl
compass (deg)
float fGc[3]
averaged precision calibrated measurement (g)
float fAlphaSqOver4
(PI / 180 * fdeltat)^2 / 4
int16_t iYs[3]
average measurement (counts)
float fRPl[3][3]
a posteriori orientation matrix
#define CHZ
float fdeltat
sensor fusion interval (s)
float fQwbOver3
Qwb / 3.
int16_t iYsFIFO[GYRO_FIFO_SIZE][3]
FIFO measurements (counts)
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
void fveqRu(float fv[], float fR[][3], float fu[], int8 itranspose)
function rotates 3x1 vector u onto 3x1 vector using 3x3 rotation matrix fR. the rotation is applied i...
Definition: matrix.c:820
void fInit_6DOF_GY_KALMAN(struct SV_6DOF_GY_KALMAN *pthisSV, struct AccelSensor *pthisAccel, struct GyroSensor *pthisGyro)
Definition: fusion.c:313
void fqAeqNormqA(Quaternion *pqA)
function normalizes a rotation quaternion and ensures q0 is non-negative
Definition: orientation.c:999
Quaternion fqPl
a posteriori orientation quaternion
float fqgErrPl[3]
gravity vector tilt orientation quaternion error (dimensionless)
float fAlphaOver2
PI / 180 * fdeltat / 2.
void fRotationVectorDegFromQuaternion(Quaternion *pq, float rvecdeg[])
computes rotation vector (deg) from rotation quaternion
Definition: orientation.c:862
float fRVecPl[3]
rotation vector
int8_t resetflag
flag to request re-initialization on next pass
float fQwCT6x3[6][3]
Qw.C^T matrix.
float q2
y vector component
Definition: orientation.h:41
void qAeqAxB(Quaternion *pqA, const Quaternion *pqB)
function compute the quaternion product qA = qA * qB
Definition: orientation.c:969
float fK6x3[6][3]
kalman filter gain matrix K
float fQv
measurement noise covariance matrix leading diagonal
float fDegPerSecPerCount
deg/s per count
float fOmega[3]
average angular velocity (deg/s)
int8_t int8
Definition: sensor_fusion.h:55
#define ONEOVER12
1 / 12
float q1
x vector component
Definition: orientation.h:40
float fAccGl[3]
linear acceleration (g) in global frame
void fWin8AnglesDegFromRotationMatrix(float R[][3], float *pfPhiDeg, float *pfTheDeg, float *pfPsiDeg, float *pfRhoDeg, float *pfChiDeg)
extract the Windows 8 angles in degrees from the Windows 8 rotation matrix
Definition: orientation.c:621

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fRun_9DOF_GBY_KALMAN ( struct SV_9DOF_GBY_KALMAN pthisSV,
struct AccelSensor pthisAccel,
struct MagSensor pthisMag,
struct GyroSensor pthisGyro,
struct MagCalibration pthisMagCal 
)

Referenced by fFuseSensors(), and fRun_6DOF_GY_KALMAN().

+ Here is the caller graph for this function: